Skip to content

gh-153400: Fall back to __NR_getrandom when SYS_getrandom is unavailable - #155762

Open
jjhelmus wants to merge 4 commits into
python:mainfrom
jjhelmus:getrandom_use_NR
Open

gh-153400: Fall back to __NR_getrandom when SYS_getrandom is unavailable#155762
jjhelmus wants to merge 4 commits into
python:mainfrom
jjhelmus:getrandom_use_NR

Conversation

@jjhelmus

@jjhelmus jjhelmus commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Fall back to the kernel-provided __NR_getrandom in configure checks, os.getrandom(), and interpreter entropy handling when libc SYS_getrandom is not available.

This makes os.getrandom() available when building against an older glibc that was itself built with kernel headers lacking the syscall, provided the current kernel headers define __NR_getrandom. This type of build is done in python-build-standalone, astral-sh/python-build-standalone#1188.

Replace libc's SYS_getrandom with the kernel-provided __NR_getrandom
in configure checks, os.getrandom(), and interpreter entropy handling.
@aisk

aisk commented Aug 14, 2026

Copy link
Copy Markdown
Member

Hi, I think this is not a trivial change, so the related issue is required.

@picnixz picnixz changed the title Use kernel-provided __NR_getrandom syscall number gh-153400: Use kernel-provided __NR_getrandom syscall number Aug 14, 2026
@picnixz

picnixz commented Aug 14, 2026

Copy link
Copy Markdown
Member

We changed to use the glibc-provided one in #155518 so I'm nt sure this change is needed anymore but maybe there is a world where neither glibc getrandom() exists nor SYS_getrandom in which case we need to fall back to __NR_getrandom.

cc @vstinner

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the commit message, you can document that __NR_getrandom comes from Linux kernel <unistd.h>, whereas SYS_getrandom comes from glibc <sys/syscall.h>.

Comment thread Python/bootstrap_hash.c Outdated
# endif
# if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
# include <sys/syscall.h> // SYS_getrandom
# include <sys/syscall.h> // __NR_getrandom

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This include should be removed, __NR_getrandom comes from <unistd.h> which is already included above.

__NR_getrandom comes the kernel header files, like /usr/include/asm/unistd_64.h on my Fedora 44. <sys/syscall.h> is the glibc header file which provides SYS_getrandom constant, but this change replace __NR_getrandom with SYS_getrandom.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the chain for __NR_getrandom is <sys/syscall.h> -> <asm/unistd.h>

For SYS_getrandom, <sys/syscall.h> -> <bits/syscall.h>

I could not find a path from <unistd.h> to either of these symbols.

Comment thread configure.ac
[
AC_LANG_SOURCE([[
#include <stddef.h>
#include <unistd.h>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include <unistd.h> // __NR_getrandom

Comment thread configure.ac
AC_LANG_SOURCE([[
#include <stddef.h>
#include <unistd.h>
#include <sys/syscall.h>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since SYS_getrandom is no longer used, <sys/syscall.h> include can be removed, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the change to falling back to __NR_getrandom only when SYS_getrandom is undefined this is include is still needed.

Comment thread configure.ac Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include <linux/random.h> // GRND_NONBLOCK

@vstinner

Copy link
Copy Markdown
Member

I don't know how Solaris, FreeBSD and OpenBSD expose their syscall numberes: __NR_getrandom or SYS_getrandom? The PR should be tested on these systems before being merged.

@jjhelmus

Copy link
Copy Markdown
Contributor Author

We changed to use the glibc-provided one in #155518 so I'm nt sure this change is needed anymore but maybe there is a world where neither glibc getrandom() exists nor SYS_getrandom in which case we need to fall back to __NR_getrandom.

This is exactly the case that python-build-standalone is running into on x86-64. The target is glibc 2.17 which does not included getrandom and the Debian package providing it is built against a a kernel that does not include SYS_getrandom. The build uses a modern UAPI kernel heads so __NR_getrandom is available.

@vstinner

Copy link
Copy Markdown
Member

This makes os.getrandom() available when building against an older glibc that was itself built with kernel headers lacking the syscall, provided the current kernel headers define __NR_getrandom.

Do you mean that glibc 2.17 doesn't provide SYS_getrandom macro?

@vstinner

Copy link
Copy Markdown
Member

This is exactly the case that python-build-standalone is running into on x86-64. The target is glibc 2.17 which does not included getrandom and the Debian package providing it is built against a a kernel that does not include SYS_getrandom. The build uses a modern UAPI kernel heads so __NR_getrandom is available.

Which Linux kernel version are you used to build Python?

@jjhelmus

jjhelmus commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Do you mean that glibc 2.17 doesn't provide SYS_getrandom macro?

Often not, glibc 2.17 was released in 2012. The the getrandom syscall was added to the kernel in 2014 with 3.17.
glibc generates syscall aliases from the kernel headers available when it is build, so if built against <3.17, the SYS_getrandom macro will not be included.

The specifics for python-build-standalone are glibc 2.19 build against kernel 3.16. So no getrandom function nor SYS_getrandom macro. Modern 7.0 UAPI kernel headers are used in the build so __NR_getrandom is available.

Note that the glib 2.17 packages in RHEL 9 and derivates likely include the macro because the syscall list was updated to include calls from the 5.4 kernel.

@vstinner

Copy link
Copy Markdown
Member

Modern 7.0 UAPI kernel headers are used in the build so __NR_getrandom is available.

I don't know "UAPI kernel headers". How do they work?

@picnixz

picnixz commented Aug 14, 2026

Copy link
Copy Markdown
Member

If we want to maximize compatibility I think we should rather check for both SYS_* and __NR_* macros then. Since we're anyway worrying about exotic platforms, we may even have the lack of __NR_* macro and getrandom() syscall and only the SYS_* macro.

@jjhelmus

Copy link
Copy Markdown
Contributor Author

I don't know "UAPI kernel headers". How do they work?

By UAPI headers, I mean the Linux kernel’s userspace API headers, the headers needed to compile userspace programs including CPython. These are distinct from the headers used to compile external kernel modules. On Debian, the userspace headers are provided by linux-libc-dev, while kernel-module development headers are provided by linux-headers-*. On Fedora and RHEL, the corresponding packages are kernel-headers and kernel-devel. This may not be the typical terminology used, the split is new to me.

python-build-standalone installs these header from Linux 7.0.12 and places them before the sysroot headers in the search path. Consequently, newer kernel syscall numbers such as __NR_getrandom are available at build time even when the older glibc headers do not define SYS_getrandom. More details are in astral-sh/python-build-standalone#1163.

Use the libc-provided SYS_getrandom syscall number when available,
falling back to the kernel-provided __NR_getrandom when necessary.
@jjhelmus

Copy link
Copy Markdown
Contributor Author

If we want to maximize compatibility I think we should rather check for both SYS_* and __NR_* macros then. Since we're anyway worrying about exotic platforms, we may even have the lack of __NR_* macro and getrandom() syscall and only the SYS_* macro.

Agreed. I'ved update the PR to use __NR_getrandom as a fallback when SYS_getrandom is undefined. This allows any of the three possibilities, getrandom(), SYS_getrandom, or __NR_getrandom to be used.

@jjhelmus jjhelmus changed the title gh-153400: Use kernel-provided __NR_getrandom syscall number gh-153400: Fall back to __NR_getrandom when SYS_getrandom is unavailable Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants